//
//  BZAudioPlayer.m
//  BZFoundation
//
//  Created by 郭艺伟 on 2017/9/28.
//  Copyright © 2017年 郭艺伟. All rights reserved.
//

#import "BZAudioPlayer.h"
#import "UIDevice+BZHelper.h"
#import <AVFoundation/AVFoundation.h>

@interface BZAudioPlayer () <AVAudioPlayerDelegate>

@property (nonatomic, strong) AVAudioPlayer *player;

@end

static dispatch_once_t onceToken;
static BZAudioPlayer *instance = nil;



@implementation BZAudioPlayer
#pragma mark - Singleton

+ (instancetype)sharedInstance {
    dispatch_once(&onceToken, ^ {
        if (!instance) {
            instance = [[self alloc] initSingleton];
        }
    });
    return instance;
}

- (id)init {
    NSAssert(NO, @"Cannot create instance of singleton");
    return nil;
}

- (id)initSingleton {
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(handleInterruptionNotification:)
                                                     name:AVAudioSessionInterruptionNotification
                                                   object:nil];
    }
    return self;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
}

#pragma mark - Output Mode

- (BOOL)switchToOutputType:(BZAudioOutputType)type error:(NSError **)error {
    AVAudioSessionPortOverride overrideType = type == BZAudioOutputTypeDefault ? AVAudioSessionPortOverrideNone:AVAudioSessionPortOverrideSpeaker;
    if ([[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:error]) {
        return [[AVAudioSession sharedInstance] overrideOutputAudioPort:overrideType error:error];
    }
    return NO;
}

#pragma mark - Interruption Notification

- (void)handleInterruptionNotification:(NSNotification *)notification {
    if (!self.isPlaying) {
        return;
    }
    
    NSInteger interruptionType = [notification.userInfo[@"AVAudioSessionInterruptionTypeKey"] integerValue];
    if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
        if ([self.delegate respondsToSelector:@selector(audioPlayerDidBeginInterruption:)]) {
            [self.delegate audioPlayerDidBeginInterruption:self];
        }
    }
    else if(interruptionType == AVAudioSessionInterruptionTypeEnded) {
        if ([self.delegate respondsToSelector:@selector(audioPlayerDidEndInterruption:)]) {
            [self.delegate audioPlayerDidEndInterruption:self];
        }
    }
}

#pragma mark - Play

- (BOOL)setURL:(NSURL *)filePath error:(NSError **)error {
    if (self.player.playing) {
        [self.player stop];
    }
    
    if (![[AVAudioSession sharedInstance] setActive:YES error:error]) {
        return NO;
    }
    
    if (![[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error: error]) {
        return NO;
    }
    
    if (![UIDevice bz_isHeadsetPluggedIn]) {
        //未插入耳机, 外放
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:error];
    }
    
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:filePath error:error];
    self.player.delegate = self;
    return self.player != nil;
}

- (BOOL)play {
    return [self.player play];
}

- (BOOL)playAudioWithURL:(NSURL *)filePath error:(NSError **)error {
    if (![self setURL:filePath error:error]) {
        return NO;
    }
    else {
        return [self play];
    }
}

- (void)playAtTime:(NSTimeInterval)time {
    [self.player playAtTime:time];
}

- (void)pause {
    [self.player pause];
}

- (BOOL)isPlaying {
    return [self.player isPlaying];
}

- (void)stop {
    [self.player stop];
}

#pragma mark - AVAudioPlayerDelegate

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    if ([self.delegate respondsToSelector:@selector(audioPlayerDidFinishPlaying:success:)]) {
        [self.delegate audioPlayerDidFinishPlaying:self success:flag];
    }
}

#pragma mark - Setter & Getter

- (NSTimeInterval)currentTime {
    return self.player.currentTime;
}

- (void)setCurrentTime:(NSTimeInterval)currentTime {
    self.player.currentTime = currentTime;
}

#pragma mark - Test

+ (void)resetSharedInstance {
    onceToken = 0; // resets the once_token so dispatch_once will run again
    instance = nil;
}


@end
